package com.yungu.swift.order.utils;

import com.yungu.swift.base.ResponseData;
import com.yungu.swift.utils.Md5Utils;
import com.yungu.swift.utils.StringUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.collections4.map.HashedMap;

import java.io.InputStream;
import java.security.PublicKey;
import java.util.HashMap;
import java.util.Map;
import java.util.Random;

import static com.yungu.swift.order.config.NacosListener.WXPAY_CONFIG;


/**
 * @Description:微信转账到银行卡
 * @Author Zerrion
 * @Date 2018/12/28 20:14
 * @Version 1.0
 */
@Slf4j
public class WxToBankBuilder {

    /**
     * 微信转账到银行卡请求url
     */
    private static final String PAY_BANK_URL = "https://api.mch.weixin.qq.com/mmpaysptrans/pay_bank";
    /**
     * 查询微信转账到银行卡请求url
     */
    private static final String QUERY_PAY_BANK_URL = "https://api.mch.weixin.qq.com/mmpaysptrans/query_bank";

    /**
     * 微信转账到银行卡
     *
     * @param collectAccount
     * @param collectName
     * @param collectBankName
     * @param amount
     * @param serialNum
     * @return
     */
    public static ResponseData<Map<String, String>> wxToBankCardData(String collectAccount, String collectName,
                                                                     String collectBankName, int amount, String serialNum) {
        //获取收款方开户行银行编码
        int bankCode = GetBankNo.getBankNo(collectBankName);
        if (bankCode == -1) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "获取不到银行编码");
        }
        String partner = WXPAY_CONFIG.getDriverWxPartner();
        String key = WXPAY_CONFIG.getDriverWxAppKey();
        Map<String, String> map = new HashedMap(16);
        //商户号
        map.put("mch_id", partner);
        //商户企业付款单号
        map.put("partner_trade_no", serialNum);
        //随机字符串
        map.put("nonce_str", Md5Utils.encode(String.valueOf(new Random().nextInt(10000))));
        map.put("bank_code", String.valueOf(bankCode));
        //付款金额
        map.put("amount", String.valueOf(amount));
        //收款方卡号/账户名 rsa加密
        String rsa = "RSA/ECB/OAEPWITHSHA-1ANDMGF1PADDING";
        try (InputStream inputStream = WxToBankBuilder.class.getResourceAsStream("/pksc8_public.pem")) {
            PublicKey pub = RsaUtil.getPublicKey(inputStream, "RSA");
            //对银行账号进行加密
            byte[] bankStr = RsaUtil.encrypt(collectAccount.getBytes(), pub, 2048, 11, rsa);
            //并转为base64格式
            String rsaBankNo = Base64.encodeBase64String(bankStr);
            map.put("enc_bank_no", rsaBankNo);
            //对银行账户名进行加密
            byte[] bankNameStr = RsaUtil.encrypt(collectName.getBytes("UTF-8"), pub, 2048, 11, rsa);
            String rsaBankName = Base64.encodeBase64String(bankNameStr);
            map.put("enc_true_name", rsaBankName);
        } catch (Exception e) {
            log.error("WxToBankBuilder wxToBankCardData read pksc8_public.pem error", e);
        }
        //签名
        String sign = PaySignBuilder.wxSignMD5(map, key);
        if (StringUtils.isEmpty(sign)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "参数 MD5签名失败");
        }
        map.put("sign", sign);
        String payXml = XmlUtils.buildXml(map);
        Map<String, String> resultMap = new HashMap<>();
        try (InputStream certPath = WxToBankBuilder.class.getResourceAsStream("/apiclient_cert.p12")) {
            String resultStr = TenpayHttpClient.doSslRequest(PAY_BANK_URL, payXml, partner, certPath);
            resultMap = XmlUtils.readValueAsMap(resultStr);
        } catch (Exception e) {
            log.error("WxToBankBuilder wxToBankCardData read apiclient_cert.p12 error", e);
        }
        if (resultMap == null || resultMap.isEmpty()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "微信转账XML解析异常");
        }
        if (!"SUCCESS".equals(resultMap.get("return_code"))) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "微信转账到银行卡通讯异常 -- " + resultMap.get("return_msg"));
        }
        if (!"SUCCESS".equals(resultMap.get("result_code"))) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "微信转账到银行卡异常 -- " + resultMap.get("err_code_des"));
        }
        return ResponseData.buildSuccessResponse("微信转账到银行卡请求成功", resultMap);
    }


    public static ResponseData<Map<String, String>> wxQueryBank(String serialNum) {
        Map<String, String> map = new HashedMap(16);
        //商户号
        map.put("mch_id", WXPAY_CONFIG.getDriverWxPartner());
        //商户企业付款单号
        map.put("partner_trade_no", serialNum);
        //随机字符串
        map.put("nonce_str", Md5Utils.encode(String.valueOf(new Random().nextInt(10000))));
        //签名
        String sign = PaySignBuilder.wxSignMD5(map, WXPAY_CONFIG.getDriverWxAppKey());
        if (StringUtils.isEmpty(sign)) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "参数MD5签名失败");
        }
        map.put("sign", sign);
        String payXml = XmlUtils.buildXml(map);
        String resultStr;
        Map<String, String> resultMap = new HashMap<>();
        try (InputStream inputStream = WxToBankBuilder.class.getResourceAsStream("/apiclient_cert.p12")) {
            //微信需要http通讯请求转账信息
            resultStr = TenpayHttpClient.doSslRequest(QUERY_PAY_BANK_URL, payXml, WXPAY_CONFIG.getDriverWxPartner(), inputStream);
            resultMap = XmlUtils.readValueAsMap(resultStr);
        } catch (Exception e) {
            log.error("WxToBankBuilder wxQueryBank read apiclient_cert.p12 error", e);
        }
        if (resultMap == null || resultMap.isEmpty()) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "查询微信转账XML解析异常");
        }
        if (!"SUCCESS".equals(resultMap.get("return_code"))) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "查询微信转账到银行卡通讯异常 -- ", resultMap);
        }
        if (!"SUCCESS".equals(resultMap.get("result_code"))) {
            return ResponseData.buildErrorResponse(ResponseData.ERROR_CODE, "查询微信转账到银行卡异常 -- ", resultMap);
        }
        return ResponseData.buildSuccessResponse("查询微信转账到银行卡请求成功", resultMap);
    }
}
